Skip to content

ext/soap: Fix SOAP classmap validation for integer keys#22884

Open
LamentXU123 wants to merge 2 commits into
php:masterfrom
LamentXU123:soap-todo
Open

ext/soap: Fix SOAP classmap validation for integer keys#22884
LamentXU123 wants to merge 2 commits into
php:masterfrom
LamentXU123:soap-todo

Conversation

@LamentXU123

Copy link
Copy Markdown
Member

Previously, SOAP only rejected packed arrays, which still allowed sparse integer-keyed arrays and mixed string integer-keyed arrays to be accepted.

Since classmap is expected to be an associative mapping, arrays containing integer keys are now rejected consistently.

@devnexen

Copy link
Copy Markdown
Member

could you add the following test please ?

--TEST--
SoapClient must not read a packed "classmap" array as a hash
--EXTENSIONS--
soap
--FILE--
<?php

class LocalClient extends SoapClient
{
    public function __doRequest(string $request, string $location, string $action, int $version, bool $oneWay = false, ?string $uriParserClass = null): ?string
    {
        echo $request, PHP_EOL;

        return <<<XML
        <?xml version="1.0" encoding="UTF-8"?>
        <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
          <SOAP-ENV:Body><ns1:doItResponse xmlns:ns1="urn:test"/></SOAP-ENV:Body>
        </SOAP-ENV:Envelope>
        XML;
    }
}

$client = new LocalClient(null, [
    'location' => 'http://example.com/',
    'uri' => 'urn:test',
    'classmap' => ['SomeType' => 'stdClass'],
]);

$property = new ReflectionProperty(SoapClient::class, '_classmap');
$property->setValue($client, ['stdClass', 'stdClass']);

$client->__soapCall('doIt', [new stdClass()]);

echo 'done', PHP_EOL;

?>
--EXPECTF--
%A
done

@LamentXU123
LamentXU123 force-pushed the soap-todo branch 2 times, most recently from 732faef to 751d593 Compare July 25, 2026 12:08
@LamentXU123

Copy link
Copy Markdown
Member Author

This is indeed a bug when SoapClient::_classmap can be reflected as a packed array :)

@devnexen

Copy link
Copy Markdown
Member

I would like to see the following in classmap_invalid_keys.phpt test :


    'sparse numeric' => [100 => 'stdClass'],
    'numeric string' => ['1' => 'stdClass'],

those new tests

--TEST--
SoapClient and SoapServer report an invalid "classmap" option differently
--EXTENSIONS--
soap
--FILE--
<?php

$classmap = ['type' => 'stdClass', 1 => 'stdClass'];

try {
    new SoapClient(null, [
        'location' => 'http://example.com/',
        'uri' => 'urn:test',
        'classmap' => $classmap,
    ]);
} catch (Throwable $e) {
    echo 'SoapClient: ', $e::class, ': ', $e->getMessage(), PHP_EOL;
}

try {
    new SoapServer(null, [
        'uri' => 'urn:test',
        'classmap' => $classmap,
    ]);
} catch (Throwable $e) {
    echo 'SoapServer: ', $e::class, ': ', $e->getMessage(), PHP_EOL;
}

?>
--EXPECT--
SoapClient: SoapFault: SoapClient::__construct(): 'classmap' option must be an associative array
SoapServer: ValueError: SoapServer::__construct(): Argument #2 ($options) "classmap" option must be an associative array
--TEST--
SoapClient reports an invalid "classmap" option as a fatal error when exceptions are disabled
--EXTENSIONS--
soap
--FILE--
<?php

new SoapClient(null, [
    'location' => 'http://example.com/',
    'uri' => 'urn:test',
    'exceptions' => false,
    'classmap' => ['type' => 'stdClass', 1 => 'stdClass'],
]);

echo 'not reached', PHP_EOL;

?>
--EXPECTF--
Fatal error: SoapClient::__construct(): 'classmap' option must be an associative array in %s on line %d

Comment thread ext/soap/soap.c Outdated
}
/* }}} */

static bool soap_class_map_is_valid(const HashTable *class_map)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

name a bit misleading since you check only the keys

Co-Authored-By: David CARLIER <devnexen@gmail.com>
Update SOAP section to clarify changes in classmap option and WSDL parsing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants